<template>
  <div class="l-rblock l-tab-page view-page">
    <l-layout class="l-tab-page" :top="44" :topMove="false">
      <template #top>
        <div class="top-panel">
          <div class="top-panel__item">
            <el-select
              style="width: 100%"
              size="mini"
              v-model="currentConfig.dbCode"
              :placeholder="$t('please select数据库')"
            >
              <el-option-group
                v-for="group in lr_dblinkTree"
                :key="group.id"
                :label="group.label"
              >
                <el-option
                  v-for="item in group.children"
                  :key="item.id"
                  :label="item.label"
                  :value="item.id"
                >
                </el-option>
              </el-option-group>
            </el-select>
          </div>
          <div class="top-panel__item" style="width: 240px">
            <el-input
              style="width: 100%"
              :placeholder="$t('please select表')"
              readonly="readonly"
              v-model="currentConfig.dbTable"
              size="mini"
            >
              <span slot="append" @click="handleAddTable">
                <el-button slot="append" icon="el-icon-more"></el-button>
              </span>
            </el-input>
          </div>
          <div>
            <el-tooltip
              :content="$t('query')"
              :enterable="false"
              placement="bottom"
              ><el-button
                class="learun-text-btn"
                type="text"
                icon="learun-icon-play-base"
                :loading="tableLoading"
                @click="loadTableData"
              />
            </el-tooltip>
          </div>
        </div>
      </template>
      <div class="l-rblock">
        <l-table
          ref="mainTable"
          :columns="columns"
          :dataSource="tableData"
          :loading="tableLoading"
          :isPage="true"
          :pageTotal="tableTotal"
          :tablePage.sync="tableCurrentPage"
          @loadPageData="turnTablePage"
        >
        </l-table>
      </div>
    </l-layout>
    <div :class="['info-wraper', { opened: infoWraperOpen }]">
      <el-form
        v-show="infoWraperOpenType == 'info'"
        style="padding: 10px 10px 0 10px"
        :model="formData"
        :rules="rules"
        size="mini"
        ref="form"
      >
        <el-form-item :label="$t('名称')" prop="f_Name">
          <el-input
            v-model="formData.f_Name"
            :placeholder="$t('please enter')"
          ></el-input>
        </el-form-item>
        <el-form-item :label="$t('编码')" prop="f_Code">
          <el-input
            v-model="formData.f_Code"
            :placeholder="$t('please enter')"
          ></el-input>
        </el-form-item>
        <el-form-item :label="$t('分类')" prop="f_Category">
          <l-tree-select
            v-model="formData.f_Category"
            :options="lr_dataItemTree(lr_dataItem['datasourceType'])"
          />
        </el-form-item>
        <el-form-item :label="$t('备注')" prop="f_Description">
          <el-input
            type="textarea"
            v-model="formData.f_Description"
            rows="6"
          ></el-input>
        </el-form-item>
      </el-form>
      <template v-if="infoWraperOpenType == 'order'">
        <el-form
          style="padding: 10px 10px 0 10px"
          size="mini"
          v-if="orders.length > 0"
        >
          <div
            class="learun-row-form-input"
            :key="index"
            v-for="(item, index) in orders"
          >
            <el-form-item :label="$t('字段')" style="margin-bottom: 8px">
              <el-autocomplete
                v-model="item.field"
                :fetch-suggestions="querySearchAsync"
              ></el-autocomplete>
            </el-form-item>

            <el-form-item :label="$t('倒序')" style="margin-bottom: 8px">
              <el-switch v-model="item.isDESC"></el-switch>
            </el-form-item>
            <el-button
              :title="$t('Delete')"
              @click="handleRemoveOrder(index)"
              class="learun-row-form-input-delete"
              circle
              plain
              size="mini"
              type="danger"
            >
              <i class="el-icon-close"></i>
            </el-button>
          </div>
        </el-form>
        <div v-if="orders.length > 0" class="mt-8" style="padding-left: 10px">
          <el-button type="primary" size="mini" @click="handleAddOrder">{{
            $t("添加排序字段")
          }}</el-button>
        </div>
        <div v-else class="learun-empty">
          <el-empty :description="$t('还没有添加排序字段')" />
          <el-button type="primary" size="mini" @click="handleAddOrder">{{
            $t("添加一个")
          }}</el-button>
        </div>
      </template>
      <template v-else-if="infoWraperOpenType == 'field'">
        <div v-if="columns.length > 0" style="padding: 10px">
          <div class="field-row" v-for="field in columns" :key="field.prop">
            <div :class="['field-row-header', getTypeClass(field)]">
              {{ getTypeName(field) }}
            </div>
            <div class="field-row-content">{{ getColNames(field) }}</div>
          </div>
        </div>
        <div v-else class="learun-empty">
          <el-empty :description="$t('暂无字段信息,请在左侧选择数据表')" />
        </div>
      </template>
    </div>
    <div class="right-side">
      <div
        :class="['vertical-btn', { opened: infoWraperOpenType == 'info' }]"
        @click="handleClickRightSideBtn('info')"
      >
        {{ $t('基础信息') }}
      </div>
      <div
        :class="['vertical-btn', { opened: infoWraperOpenType == 'order' }]"
        @click="handleClickRightSideBtn('order')"
      >
        {{ $t('排序字段') }}
      </div>
      <div
        :class="['vertical-btn', { opened: infoWraperOpenType == 'field' }]"
        @click="handleClickRightSideBtn('field')"
      >
        {{ $t('字段信息') }}
      </div>
    </div>

    <l-codetable-selectdialog
      :visible.sync="dbtableSelectdialog"
      :dbCode="currentConfig.dbCode"
      :isOkClose="false"
      :multiple="false"
      @select="dbSelect"
    >
    </l-codetable-selectdialog>
  </div>
</template>
<script>
const apiCodeTable = window.$api.data.codeTable;
const api = window.$api.data.dbsource;
export default {
  data() {
    return {
      infoWraperOpen: true,
      infoWraperOpenType: "info",
      dbtableSelectdialog: false,
      tableMap: {},

      formData: {
        f_Name: "",
        f_Code: "",
        f_Category: "",
        f_Description: "",
      },
      rules: {
        f_Name: [{ required: true, message: "please enter" }],
        f_Category: [{ required: true, message: "please select" }],
        f_Code: [
          { required: true, message: "please enter" },
          {
            validator: this.lr_existDbFiled,
            keyValue: () => {
              return this.formData.f_Id;
            },
            tableName: "lr_base_datasource",
            keyName: "f_Id",
            trigger: "null",
          },
        ],
      },

      currentConfig: {},

      orders: [],
      columns: [],

      tableData: [],

      tableLoading: false,
      tableTotal: 0,
      tablePageSize: 50,
      tableCurrentPage: 1,
    };
  },
  created() {
    this.lr_loadDblink();
  },
  computed: {},
  methods: {
    handleClickRightSideBtn(type) {
      if (this.infoWraperOpenType != type) {
        this.infoWraperOpenType = type;
        this.infoWraperOpen = true;
      } else {
        this.infoWraperOpenType = "";
        this.infoWraperOpen = false;
      }
    },
    handleAddTable() {
      if (this.currentConfig.dbCode) {
        this.dbtableSelectdialog = true;
      } else {
        this.$message({
          message: this.$t("please select数据库"),
          type: "warning",
        });
      }
    },
    async dbSelect(obj, showLoading, hideLoading) {
      if (!this.formData.f_Code) {
        this.formData.f_Code = obj[0].f_TableName;
      }
      if (!this.formData.f_Name) {
        this.formData.f_Name = obj[0].f_Description || obj[0].f_TableName;
      }

      showLoading();
      this.currentConfig.dbTable = obj[0].f_TableName;
      const { dbCode, dbTable } = this.currentConfig;
      const key = `${dbCode}_${dbTable}`;
      const codeTables = await this.$awaitWraper(
        apiCodeTable.getList(dbCode, dbTable)
      );
      if (codeTables) {
        this.tableMap[key] = codeTables[0].lr_db_codecolumnsList.map((t) => ({
          label: t.f_Description
            ? `${t.f_DbColumnName}(${t.f_Description})`
            : t.f_DbColumnName,
          id: t.f_DbColumnName,
          name: t.f_DbColumnName,
          csType: t.f_CsType,
          isIdentity: t.f_IsIdentity == 1,
          isPrimary: t.f_IsPrimaryKey == 1,
          isNullable: t.f_IsNullable == 1,
          coment: t.f_Description,
        }));
      }
      this.dbtableSelectdialog = false;
      this.columns = this.tableMap[key].map((t) => ({
        prop: t.name.toLowerCase(),
        label: t.coment || t.name,
        csType: t.csType,
        width: 120,
      }));
      this.$refs.mainTable.doLayout();
      hideLoading();

      // 加载数据
      this.loadTableData();
    },
    async loadTableData(isNotFirst) {
      const { dbCode, dbTable } = this.currentConfig;
      if (!dbCode) {
        this.$message({
          type: "error",
          message: this.$t(`please select数据库`),
        });
        return;
      }

      if (!dbTable) {
        this.$message({
          type: "error",
          message: this.$t(`please select数据表`),
        });
        return;
      }

      if (!isNotFirst) {
        this.tableCurrentPage = 1;
      }
      this.tableLoading = true;
      let queryData = {
        rows: this.tablePageSize,
        page: this.tableCurrentPage,
        sidx: this.columns[0].prop,
      };

      const res = await this.$awaitWraper(
        api.getViewPageByEntity(queryData, {
          f_DbId: "learun_view",
          f_Sql: this.getSettingJson(),
        })
      );
      if (res) {
        this.tableData = res.rows;
        this.tableTotal = res.records;
      } else {
        this.tableData = [];
        this.tableTotal = [];
      }

      this.tableLoading = false;
    },
    turnTablePage({ rows }) {
      this.tablePageSize = rows;
      this.loadTableData(true);
    },

    getSettingJson() {
      const { dbCode, dbTable } = this.currentConfig;
      const settingJson = {
        orders: this.$deepClone(this.orders),
        type: "table",
        sqls: [
          {
            dbTable,
            dbCode,
          },
        ],
        columns: this.columns.map((t) => ({
          prop: t.prop,
          label: t.label,
          csType: t.csType,
        })),
      };
      return this.lr_AESEncrypt(JSON.stringify(settingJson), "David");
    },

    /**排序字段设置 */
    handleAddOrder() {
      this.orders.push({
        field: "",
        isDESC: false,
      });
    },
    handleRemoveOrder(index) {
      this.orders.splice(index, 1);
    },
    async querySearchAsync(queryString, cb) {
      const list = this.columns;
      const res = queryString
        ? list.filter(
            (t) =>
              t.prop.indexOf(queryString) != -1 ||
              t.label.indexOf(queryString) != -1
          )
        : list;
      cb(
        res.map((t) => {
          return { value: this.getColNames(t) };
        })
      );
    },

    /**获取字段信息*/
    getColNames({ prop, label }) {
      let name = prop;
      if (prop != label) {
        name = `${prop}(${label})`;
      }

      return name;
    },
    getTypeClass({ csType }) {
      switch (csType) {
        case "string":
        case "text":
          return "str";
        case "int":
        case "long":
        case "short":
        case "decimal":
        case "double":
        case "float":
          return "num";
        case "DateTime":
          return "date";
        case "bool":
          return "bool";
        default:
          return "";
      }
    },
    getTypeName({ csType }) {
      switch (csType) {
        case "string":
        case "text":
          return "字符";
        case "int":
        case "long":
        case "short":
        case "decimal":
        case "double":
        case "float":
          return "数字";
        case "DateTime":
          return "日期";
        case "bool":
          return "布尔";
        default:
          return csType;
      }
    },

    resetForm() {
      this.formData.f_Id = "";
      this.currentConfig = {};
      this.orders = [];

      this.$formClear(this.$refs.form);

      this.infoWraperOpenType = "info";
      this.infoWraperOpen = true;

      this.tableData = [];
      this.columns = [];
      this.$refs.mainTable.doLayout();
    },
    // 校验表单
    async validateForm() {
      let valid = await this.$formValidateWraper(this.$refs.form);
      if (valid) {
        if (this.orders.findIndex((t) => !t.field) > -1) {
          this.$message({
            type: "error",
            message: this.$t(`请完善排序字段设置`),
          });
          return false;
        }
        const { dbCode, dbTable } = this.currentConfig;
        if (!dbCode) {
          this.$message({
            type: "error",
            message: this.$t(`please select数据库`),
          });
          return false;
        }
        if (!dbTable) {
          this.$message({
            type: "error",
            message: this.$t(`please select数据表`),
          });
          return false;
        }
        return true;
      }

      return false;
    },
    setForm(data) {
      this.formData = {
        f_Id: data.f_Id,
        f_Name: data.f_Name,
        f_Code: data.f_Code,
        f_Category: data.f_Category,
        f_Description: data.f_Description,
      };
      const { orders, sqls, columns } = JSON.parse(data.f_Sql);
      this.orders = orders;
      this.columns = columns.map((t) => ({ ...t, width: 120 }));
      const { dbCode, dbTable } = sqls[0];
      this.currentConfig = { dbCode, dbTable };
      this.$refs.mainTable.doLayout();

      this.loadTableData();
    },
    getForm() {
      const postData = {
        f_Name: this.formData.f_Name,
        f_Code: this.formData.f_Code,
        f_Category: this.formData.f_Category,
        f_Description: this.formData.f_Description,

        f_DbId: "learun_view",
        f_Type: 1, // 表格视图
        f_Sql: this.getSettingJson(),
      };
      return postData;
    },
  },
};
</script>

<style lang="scss" scoped>
@import "@/core/styles/variables.scss";
.view-page {
  display: flex;
}
.right-side {
  position: relative;
  height: 100%;
  width: 32px;
  min-width: 32px;
  background-color: #fff;
  border-left: 1px solid $border-color-base;
  flex-grow: 2;
}
.vertical-btn {
  position: relative;
  color: $heading-color;
  padding: 4px;
  text-align: center;
  border-bottom: 1px solid $border-color-base;
  cursor: pointer;
  &:hover {
    color: $primary-color;
  }
  &.opened {
    color: $primary-color;
    &::after {
      content: "";
      height: 100%;
      width: 1px;
      background-color: #fff;
      position: absolute;
      top: 0;
      left: -1px;
    }
  }
}
.info-wraper {
  height: 100%;
  width: 0;
  transition: 0.3s all;
  background-color: #fff;
  flex-grow: 2;
  opacity: 0;
  overflow: auto;

  &.opened {
    width: 320px;
    min-width: 320px;
    border-left: 1px solid $border-color-base;
    opacity: 1;
  }
}
.top-panel {
  position: relative;
  height: 40px;
  width: 100%;
  background-color: #fff;
  border-bottom: 1px solid $border-color-split;

  display: flex;
  align-items: center;
  padding-left: 8px;

  &__item {
    width: 200px;
    margin-right: 8px;
  }
}

.field-row {
  position: relative;
  display: flex;
  height: 40px;
  box-shadow: 0 2px 4px 0 rgb(0 0 0 / 8%);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 8px;
  &:last-child {
    margin-bottom: 0;
  }

  &-header {
    width: 40px;
    min-width: 40px;
    height: 100%;
    line-height: 40px;
    text-align: center;
    background-color: $info-color;
    color: #fff;

    // 数字 ，日期， 布尔
    &.str {
      background-color: $primary-color;
    }
    &.num {
      background-color: $success-color;
    }
    &.date {
      background-color: $warning-color;
    }
    &.bool {
      background-color: $error-color;
    }
  }

  &-content {
    border: 1px solid $border-color-base;
    border-left: 0;
    width: 100%;
    height: 100%;
    line-height: 38px;
    padding-left: 8px;
  }
}

.learun-empty {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .el-empty {
    padding-top: 0;
  }
}
</style>